package net.lzzy.practices.services;

import net.lzzy.practices.constants.Messages;
import net.lzzy.practices.entities.Chapter;
import net.lzzy.practices.entities.Option;
import net.lzzy.practices.entities.Question;
import net.lzzy.practices.repositories.ChapterRepository;
import net.lzzy.practices.repositories.OptionRepository;
import net.lzzy.practices.repositories.QuestionRepository;
import net.lzzy.practices.utils.AuthUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.UUID;

/**
 * @author  Jaymo on 2022/6/1
 */
@Service
public class QuestionServiceImpl implements  QuestionService{

    private  final QuestionRepository repository ;
    private  final ChapterRepository cRepository;
    private  final OptionRepository oRepository;

    @Autowired
    public QuestionServiceImpl(QuestionRepository repository, ChapterRepository cRepository, OptionRepository oRepository) {
        this.repository = repository;
        this.cRepository = cRepository;
        this.oRepository = oRepository;

    }


    @Override
    public List<Question> get(UUID chapterId) {
        return repository.findQuestionsByChapterIdOrderByOrdinal(chapterId);
    }

    @Transactional(rollbackFor =  Exception.class)
    @Override
    public Question add(UUID chapterId, Question question, String token) {
        Chapter chapter = cRepository.findById(chapterId).orElse(null);
        if (chapter == null){
            return  null;
        }
        UUID teacherId = chapter.getCourse().getTeacher().getId();
        if (AuthUtils.invalid(teacherId, token)) {
            return  null;
        }
      question.setChapter(chapter);
        return  repository.save(question);
    }

    @Override
    public Question update(UUID id, Question question, String token) {
        Question old = checkQuestion(id,token);
        if (old ==null) {return  null;}
        old.setAnalysis(question.getAnalysis());
        old.setContent(question.getContent());
        old.setOrdinal(question.getOrdinal());
        old.setType(question.getType());
        return  repository.save(old);
    }

    private  Question checkQuestion(UUID id,String token){
        Question old = getById(id);
        if (old ==null){
            return  null;
        }
        UUID teacherId = old.getChapter().getCourse().getTeacher().getId();
        if (AuthUtils.invalid(teacherId,token)){
            return  null;
        }
        return  old;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Messages remove(UUID id, String token) {
        Question old = getById(id);
        if (old==null){
            return  Messages.WRING_ID;
        }
        UUID teacherId = old.getChapter().getCourse().getTeacher().getId();
        if (AuthUtils.invalid(teacherId,token)){
            return  Messages.No_PERMISSION;
        }
        oRepository.deleteAll(old.getOptions());
        repository.delete(old);
        return  Messages.SUCCESS;
    }

    @Override
    public Question addOption(UUID questionId, Option option, String token) {
       Question question = checkQuestion(questionId,token);
       if (question ==null){
           return  null;
       }
       option.setQuestion(question);
       oRepository.save(option);
       return  getById(questionId);
    }

    @Override
    public Question removeOption(UUID id, String token) {
        Option option = oRepository.findById(id).orElse(null);
        if (option == null){
            return  null;
        }
        UUID questionId = option.getQuestion().getId();
        UUID teacherId = option.getQuestion().getChapter().getCourse().getTeacher().getId();
        if (AuthUtils.invalid(teacherId,token)){
            return  null;
        }
        oRepository.delete(option);
        return  getById(questionId);
    }

    @Override
    public Question getById(UUID id) {
   return  repository.findById(id).orElse(null);
    }

    @Override
    public Integer countBy(UUID chapterId) {
      return  repository.countAllByChapterId(chapterId);
    }
}
